#ifndef OSG_QT_WIDGET
#define OSG_QT_WIDGET

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Compatibility>

#include <osgViewer/GraphicsWindow>

#include <QMutex>
#include <QEvent>
#include <QQueue>
#include <QSet>

class QInputEvent;
class QGestureEvent;

namespace osgViewer {
    class ViewerBase;
}

void setViewer(osgViewer::ViewerBase *viewer, QWidget* widget, int interval = 0);

class QLCDNumber;
class OSGWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Compatibility
{
    typedef QOpenGLWidget inherited;

    double mLastTime;
    QLCDNumber* mFPSWidget;
public:

    OSGWidget(QWidget* parent = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
    virtual ~OSGWidget();

    void updateFPS();

    inline void setGraphicsWindow( osgViewer::GraphicsWindow* gw ) { _gw = gw; }
    inline osgViewer::GraphicsWindow* getGraphicsWindow() { return _gw; }
    inline const osgViewer::GraphicsWindow* getGraphicsWindow() const { return _gw; }

    inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
    virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; }
    
    inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
    void setTouchEventsEnabled( bool e );

    void setKeyboardModifiers( QInputEvent* event );

    virtual void keyPressEvent( QKeyEvent* event );
    virtual void keyReleaseEvent( QKeyEvent* event );
    virtual void mousePressEvent( QMouseEvent* event );
    virtual void mouseReleaseEvent( QMouseEvent* event );
    virtual void mouseDoubleClickEvent( QMouseEvent* event );
    virtual void mouseMoveEvent( QMouseEvent* event );
    virtual void wheelEvent( QWheelEvent* event );
    virtual bool gestureEvent( QGestureEvent* event );

protected:
    virtual bool event( QEvent* event );
    virtual void moveEvent( QMoveEvent* event );
    virtual void resizeEvent( QResizeEvent* event );

    virtual void initializeGL() Q_OVERRIDE(inherited);
    virtual void resizeGL(int w, int h) Q_OVERRIDE(inherited);
    virtual void paintGL() Q_OVERRIDE(inherited);
    
    int getNumDeferredEvents()
    {
        QMutexLocker lock(&_deferredEventQueueMutex);
        return _deferredEventQueue.count();
    }
    void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
    {
        QMutexLocker lock(&_deferredEventQueueMutex);

        if (removeEventType != QEvent::None)
        {
            if (_deferredEventQueue.removeOne(removeEventType))
                _eventCompressor.remove(eventType);
        }

        if (_eventCompressor.find(eventType) == _eventCompressor.end())
        {
            _deferredEventQueue.enqueue(eventType);
            _eventCompressor.insert(eventType);
        }
    }
    void processDeferredEvents();

    osgViewer::GraphicsWindow* _gw;

    QMutex _deferredEventQueueMutex;
    QQueue<QEvent::Type> _deferredEventQueue;
    QSet<QEvent::Type> _eventCompressor;

    bool _touchEventsEnabled;

    bool _forwardKeyEvents;
    qreal _devicePixelRatio;
};

#endif
